import 'dart:io';
import 'dart:typed_data';

/**
 * Complete the message sending and receiving processing with the server.
 */
abstract class SocketUtil {
  const SocketUtil();
  factory SocketUtil.generate({bool secure = false}) {
    return _WebSocketUtil(secure);
  }
  void connect(String host, int port, Uint8List connectProtoData,
      void Function(dynamic) onResult);
  void connect2(String host, int port, Uint8List connectProtoData,
      void Function(dynamic) onResult);
  void disconnect({void Function(dynamic) onResult});
  void setListener(
      void Function(Uint8List data) recv, void Function(dynamic) error);
  void send(Uint8List data);
  void getStatus();
}

class _WebSocketUtil extends SocketUtil {
  String _host;
  int _port;
  final bool _secure;
  WebSocket _socket;
  void Function(Uint8List data) _recv;
  void Function(dynamic error) _error;
  _WebSocketUtil(this._secure) : super();

  @override
  void connect(String host, int port, Uint8List connectProtoData,
      void Function(dynamic) onResult) {
    print('connect start:');
    this._host = host;
    this._port = port;
    var url = '${_secure ? "wss" : "ws"}://$host:$port/chat';
    print('url: $url');
    WebSocket.connect(url).timeout(Duration(seconds: 15)).then((socket) {
      print('connect send data: before');
      _socket = socket;
      _socket.listen((message) {
        print('listener recv data: ${message.length}');
        //TODO: connectProtoAckData
        // _socket.listen(_onData, onDone: _onDone, onError: _onError);
        onResult(message);
      }, onError: (error) {
        print('listener recv error: $error');
        onResult(error);
      }, onDone: () {
        print('listener recv done: ');
        onResult(null);
      });
      send(connectProtoData);
      print('connect send data: after');
    }).catchError((error) {
      print('connect error: $error');
    });
    print('connect end:');


    // WebSocket.connect(url).timeout(timeLimit)

    // try {
    //   print('connect send data: 1');
    //   _socket =
    //       await WebSocket.connect('${_secure ? "wss" : "ws"}://$host:$port/');
    //   print('connect send data: 2');
    //   _socket?.listen((message) {
    //     //TODO: connectProtoAckData
    //     _socket?.listen(_onData, onDone: _onDone, onError: _onError);
    //     onResult(message);
    //   }, onError: (error) {
    //     onResult(error);
    //   }, onDone: () {
    //     onResult(null);
    //   });
    //   print('connect send data: 3');
    //   send(connectProtoData);
    //   print('connect send data: 4');
    // } catch (e) {
    //   print('connect send data: error');
    //   onResult(e);
    // }
  }

  @override
  void connect2(String host, int port, Uint8List connectProtoData,
      void Function(dynamic) onResult) {}

  @override
  void disconnect({void Function(dynamic) onResult}) {
    _socket?.listen((_) {});
    _socket?.close(0, 'The client actively disconnects.');
    _socket = null;
    if (null != onResult) {
      onResult(null);
    }
  }

  @override
  void send(Uint8List data) {
    _socket?.add(data);
  }

  @override
  void setListener(
      void Function(Uint8List data) recv, void Function(dynamic) error) {
    _recv = recv;
    _error = error;
  }

  @override
  void getStatus() {}

  void _onData(dynamic message) {
    if (_recv != null) {
      _recv(message);
    }
  }

  void _onError(dynamic error) {
    if (null != _error) {
      _error(error);
    }
  }

  void _onDone() {}
  void _reset() {}
}
